/*
 * @Author: aleimu
 * @Date: 2021-03-24 16:25:16
 * @Description: 深入 hook 系列 -1
 * 1. seState派发更新函数的执行，就会让整个function组件从头到尾执行一次,复合组件中的其他组件也被渲染了,造成了性能浪费
 * 2. 几个常用的 hook 使用示例
 */

import React, { useState, useMemo, useRef, useReducer } from 'react'
import ReactDOM from 'react-dom';


/* 自定义hooks 用于格式化数组将小写转成大写 */
function useFormatList(list) {
    // 直接操作
    // return list.map(item => {
    //     console.log(1111) // 可以看到setNumber时这里也被重复执行了.
    //     return item.toUpperCase()
    // })

    // 配合useMemo使用,避免非必要的渲染,仅当list这个参数发生变化时才重新执行函数体
    return useMemo(() => list.map(item => {
        console.log(1111)
        return item.toUpperCase()
    }), [list])
    // useCallback(fn, deps) 相当于 useMemo(() => fn, deps)
}


function testFunc() {
    console.log('testFunc running')
}

function callFunc() {
    console.log('callFunc running')
}

/* 父组件传过来的list = [ 'aaa' , 'bbb' , 'ccc'  ] */
function Index({ list }) {
    const [number, setNumber] = useState(0)
    const [func, setFunc] = useState(testFunc(), callFunc()) // 参数也可以是函数,并且第二个参数为可选的回调函数，它将在 setState 完成合并并重新渲染组件后执行
    const newList = useFormatList(list) //一个简单的自定义 hooks

    return <div>
        <div className="list" >
            {newList.map(item => <div key={item} >{item}</div>)}
        </div>
        <div className="number" >
            <div>{number}</div>
            <button onClick={() => {
                setNumber(number + 1) // 直接更新
                setNumber(number => number + 1) // 函数形式和上面的方式有啥区别?感觉是当旧 state 值比较复杂时如只要更新 state 值中某一部分
                console.log(number) /* 由于setNumber是异步的,这里的number是不能够即使改变的,只有当Index这个组件重新渲染时这里才会显示正确的值  */
            }} >add</button>
        </div >

    </div >
}

// useRef的使用实例, 点击按钮,将光标指向输入框
function TextInputWithFocusButton() {
    const inputEl = useRef(null);
    const onButtonClick = () => {
        // `current` 指向已挂载到 DOM 上的文本输入元素
        inputEl.current.focus();
    };
    return (
        <>
            <input ref={inputEl} type="text" />
            <button onClick={onButtonClick}>Focus the input</button>
        </>
    );
}

// 以下为useReducer的使用实例,感觉就是字典函数
const initialState = { count: 0 };
function reducer(state, action) {
    switch (action.type) {
        case 'increment':
            return { count: state.count + 1 };
        case 'decrement':
            return { count: state.count - 1 };
        default:
            throw new Error();
    }
}
function Counter() {
    const [state, dispatch] = useReducer(reducer, initialState);
    return (
        <>
            Count: {state.count}
            <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
            <button onClick={() => dispatch({ type: 'increment' })}>+</button>
        </>
    );
}

const App = () => {
    return (
        <div>
            <Index list={['a', 'b', 'c']} />
            <TextInputWithFocusButton>测试</TextInputWithFocusButton>
            <Counter />
        </div>
    )
}

export default App



